package cn.cms.service;

import cn.cms.webcommon.ReqBo;
import cn.cms.webcommon.ResBo;
import cn.cms.dao.PageDao;
import cn.cms.dao.SysRoleDao;
import cn.cms.dao.SysUserDao;
import cn.cms.model.SysRole;
import cn.cms.model.SysUser;
import cn.cms.util.StringUtil;
import cn.cms.util.security.Digests;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class SysUserService {

    private static final Logger logger = LoggerFactory.getLogger(SysUserService.class);

    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysRoleDao sysRoleDao;

    public static final int HASH_INTERATIONS = 1024;
    private static final int SALT_SIZE = 8;
//    private static final String DEFAULT_PWD = "q@12345";

    public void save(SysUser sysUser) {
        sysUserDao.save(sysUser);
    }

    public ResBo chgPwd(ReqBo reqBo) {
        ResBo resBo = new ResBo();
        try {
            SysUser sysUser = (SysUser) reqBo.getParam("sysUser");
            SysUser oldSysUser = sysUserDao.get(sysUser.getId());
            if (this.encodePassword(oldSysUser.getSalt(), sysUser.getEncryptedPassword()).equals(oldSysUser.getEncryptedPassword())) {
                oldSysUser.setEncryptedPassword(this.encodePassword(oldSysUser.getSalt(), sysUser.getPlainPassword()));
                sysUserDao.update(oldSysUser);
                return resBo;
            } else {
                resBo.setSuccess(false);
                resBo.setErrMsg("旧密码输入不正确！");
                return resBo;
            }
        } catch (DecoderException e) {
            logger.error("", e);
            resBo.setSuccess(false);
            resBo.setErrMsg(e.getMessage());
            return resBo;
        }
    }

    public void delete(Long id) {
        sysUserDao.delete(id);
    }

    public void delete(SysUser sysUser) {
        sysUserDao.delete(sysUser);
    }

    public SysUser get(Long id) {
        return sysUserDao.get(id);
    }

    public void update(SysUser sysUser) {
        sysUserDao.update(sysUser);
    }

    public SysUser get(SysUser sysUser) {
        return sysUserDao.get(sysUser);
    }

    public SysUser getByLoginName(String loginName) {
        return sysUserDao.getByLoginName(loginName);
    }

    public List<SysUser> getListPage(PageDao pageDao, String keyWords) {
        if (!StringUtil.isSpaceOrNull(keyWords)) {
            keyWords = "%" + keyWords + "%";
        }
        List<SysUser> sysUsers = sysUserDao.getList(pageDao, keyWords);

        sysUsers.forEach(k -> {
            String[] roleIds = ((k.getRoleIds() == null) ? "" : k.getRoleIds()).split(",");
            List<Integer> roleIdList = new ArrayList<>();
            for (String roleId : roleIds) {
                if (!StringUtil.isSpaceOrNull(roleId)) {
                    roleIdList.add(Integer.valueOf(roleId));
                }
            }
            if (roleIdList.size() > 0) {
                List<SysRole> roles = sysRoleDao.get(roleIdList);
                StringBuilder roleDetail = new StringBuilder();
                roles.forEach(l -> {
                    roleDetail.append(l.getRoleName()).append(",");
                });
                if (roleDetail.length() > 0) {
                    k.setRoleDetail(roleDetail.substring(0, roleDetail.length() - 1));
                }
            }
        });
        return sysUsers;
    }

    public ResBo login(ReqBo reqBo) {
        ResBo resBo = new ResBo();
        String userName = (String) reqBo.getParam("userName");
        String userPassword = (String) reqBo.getParam("userPassword");
        Long userId = null;
        if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(userPassword)) {
            SysUser sysUser = sysUserDao.getByLoginName(userName);
            if (sysUser != null) {
                if (sysUser.STATE_ON.equals(sysUser.getState())) {
                    try {
                        byte[] salt = Hex.decodeHex(sysUser.getSalt().toCharArray());
                        byte[] hashPassword = Digests.sha1(userPassword.getBytes(), salt, HASH_INTERATIONS);
                        String encryptedPassword = Hex.encodeHexString(hashPassword);
                        if (encryptedPassword.equals(sysUser.getEncryptedPassword())) {
                            resBo.addResult("sysUser", sysUser);
                        } else {
                            resBo.setSuccess(false);
                            resBo.setErrMsg("密码不正确！");
                            return resBo;
                        }
                        SysUser sysUser1 = sysUserDao.getUser(userName, Hex.encodeHexString(hashPassword));
                    } catch (DecoderException e) {
                        e.printStackTrace();
                    }
                } else {
                    resBo.setSuccess(false);
                    resBo.setErrMsg("此账号已被禁用，请联系系统管理员！");
                    return resBo;
                }
            } else {
                resBo.setSuccess(false);
                resBo.setErrMsg("账号不存在！");
                return resBo;
            }
        } else {
            resBo.setSuccess(false);
            resBo.setErrMsg("用户名或者密码不能为空！");
            return resBo;
        }
        return resBo;
    }

    public boolean register(SysUser sysUser) {
        if (isLoginNameExist(sysUser.getLoginName())) {
            return false;
        }
        sysUser.setRegisterDate(new Date());
        Long id = sysUserDao.save(sysUser);
        sysUser.setId(id);
        // 重置密码
        this.resetPwd(sysUser);
        return true;
    }

    public boolean modify(SysUser sysUser) {
        SysUser oldSysUser = sysUserDao.get(sysUser.getId());
        oldSysUser.setRealName(sysUser.getRealName());
        oldSysUser.setEmail(sysUser.getEmail());
        oldSysUser.setTelephone(sysUser.getTelephone());
        oldSysUser.setDepartment(sysUser.getDepartment());
        oldSysUser.setLevel(sysUser.getLevel());
        sysUserDao.update(oldSysUser);
        return true;
    }

    public boolean modifyRoles(SysUser sysUser) {
        SysUser oldSysUser = sysUserDao.get(sysUser.getId());
        oldSysUser.setRoleIds(sysUser.getRoleIds());
        sysUserDao.update(oldSysUser);
        return true;
    }

    public ResBo resetPwd(SysUser sysUser) {
        ResBo resBo = new ResBo();
        SysUser oldSysUser = sysUserDao.get(sysUser.getId());
        try {
            byte[] salt = Digests.generateSalt(SALT_SIZE);
            // 设置随机密码
            oldSysUser.setPlainPassword(RandomStringUtils.randomAlphabetic(10));
            oldSysUser.setSalt(Hex.encodeHexString(salt));
            oldSysUser.setEncryptedPassword(Hex.encodeHexString(Digests.sha1(oldSysUser.getPlainPassword().getBytes(), salt, HASH_INTERATIONS)));
            sysUserDao.update(oldSysUser);
            resBo.addResult("newPwd", oldSysUser.getPlainPassword());
        } catch (Exception e) {
            logger.error("", e);
            resBo.setSuccess(false);
            resBo.setErrMsg(e.getMessage());
            return resBo;
        }
        return resBo;
    }

    public boolean isLoginNameExist(String name) {
        return sysUserDao.getByLoginName(name) != null;
    }

    private String encodePassword(String saltStr, String password) throws DecoderException {
        byte[] salt = Hex.decodeHex(saltStr.toCharArray());
        byte[] hashPassword = Digests.sha1(password.getBytes(), salt, HASH_INTERATIONS);
        return Hex.encodeHexString(hashPassword);
    }

}
